/*
 * Copyright (C) 2023 HiHope Open Source Organization .
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 *
 * limitations under the License.
 */

#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>

#include "ohos_init.h"
#include "cmsis_os2.h"
#include "iot_errno.h"
#include <hi_watchdog.h>

#include "net_config.h"
#include "pzcar_wheel_ctrl.h"
#ifdef SUPPORT_KV_STORE
#include "kv_store.h"
#endif
extern PzCarInfo g_carInfo;

//监听事件回调函数
static WifiEvent g_eventListener = {
    .OnWifiConnectionChanged = OnWifiConnectionChanged,  // STA连接状态发生变化
    .OnWifiScanStateChanged  = OnWifiScanStateChanged,   // STA扫描结果发生变化
    .OnHotspotStateChanged   = OnHotspotStateChanged,    // AP连接状态发生变化
    .OnHotspotStaJoin        = OnHotspotStaJoin,         // AP有STA接入
    .OnHotspotStaLeave       = OnHotspotStaLeave,        // AP有STA退出连接
};
WifiErrorCode RegisterWifiEventListener(void)
{
    return RegisterWifiEvent(&g_eventListener);
}
WifiErrorCode UnRegisterWifiEventListener(void)
{
    return UnRegisterWifiEvent(&g_eventListener);
}

void NetCtrlTask(void)
{
    CarMode eCm = eMode_Max;
    NetState eNst = Net_ST_MAX;
    WifiErrorCode retCode = -1;

    retCode = RegisterWifiEventListener();
    printf("%s: RegisterWifiEventListener: retCode[%d]\n", __func__, retCode);

    #ifdef SUPPORT_KV_STORE
    int rets = UtilsGetValue("ssid", ssid, 64);  //ret[>0] OK, [<0] NG
    int retp = UtilsGetValue("pswd", pswd, 64);  //ret[>0] OK, [<0] NG
    //printf("%s: [%d] UtilsGetValue(ssid[%s])\n", __func__, rets, ssid);
    //printf("%s: [%d] UtilsGetValue(pswd[%s])\n", __func__, retp, pswd);

    // 确认到系统的KV_STORE中已经保存有上一次连接上的热点的信息
    // 尝试用已有信息自动连接上一次的热点
    if ((rets > 0) && (retp > 0)) {
        if (g_carInfo.staInited == 0) {  // 再进入STA模式
            if (WIFI_SUCCESS == StartStation()) {
                g_carInfo.staInited = 1;
            }
        }
    }
    #endif

    while (1) {
        #if 0
        // 如果打开这句，当退出NetCtrl模式时，会关闭所有网络
        // 包括已经配好的网络也会断开，重新进入NetCtrl模式时，需要重新配网
        if (g_carInfo.e_CM != eMode_NetCtrl) {
            break;
        }
        #endif

        //printf("%s: eMode_NetCtrl: e_NetMode[%d] e_NetST[%d]\n",
        //        __func__, g_carInfo.e_NetMode, g_carInfo.e_NetST);

        //-----------------------------------------------------
        // Net_MODE_NET_SERVER 模式下，网络状态只有：Net_ST_DisCon || Net_ST_Conned
        // 这两种状态下，分别出于AP模式和STA模式，都需要打开服务器。
        if (g_carInfo.e_NetST == Net_ST_DisCon) {  // 未连接STA，进入AP模式
            if (g_carInfo.staInited == 1) {  // 先确保关闭STA模式
                if (WIFI_SUCCESS == StopStation()) {
                    g_carInfo.staInited = 0;
                }
            }
            if (g_carInfo.apInited == 0) {  // 再进入AP模式
                if (WIFI_SUCCESS == StartHotspot()) {
                    g_carInfo.apInited = 1;
                }
            }
        } else if (g_carInfo.e_NetST == Net_ST_Conned) {  // 已连接STA
            if (g_carInfo.apInited == 1) {  // 先确保关闭AP模式
                if (WIFI_SUCCESS == StopHotspot()) {
                    g_carInfo.apInited = 0;
                }
            }
            if (g_carInfo.staInited == 0) {  // 再进入STA模式
                if (WIFI_SUCCESS == StartStation()) {
                    g_carInfo.staInited = 1;
                }
            }
        }

        #if SERVER_TCP
        if (g_carInfo.tcpServRecvTaskId == NULL) {
            g_carInfo.tcpServRecvTaskId = TcpServRecvTaskEntry();
        }
        #endif
        #if SERVER_UDP
        if (g_carInfo.udpServRecvTaskId == NULL) {
            g_carInfo.udpServRecvTaskId = UdpServRecvTaskEntry();
        }
        #endif

        //-----------------------------------------------------
        // 如果进入配网模式 e_NetMode[Net_MODE_NET_CONFIG]&e_NetST[Net_ST_Config]
        // 不管是第1次配网，还是重新配网，都走下面的流程
        if ((g_carInfo.e_NetMode == Net_MODE_NET_CONFIG) ||
            (g_carInfo.e_NetST == Net_ST_Config)) {
            if (g_carInfo.staInited == 0) {  // 未连接STA，第1次配网
                if (g_carInfo.apInited == 0) {
                    if (WIFI_SUCCESS == StartHotspot()) {
                        g_carInfo.apInited = 1;
                    }
                }
                if (flag == flag_3) {
                    if (WIFI_SUCCESS == StartStation()) {
                        g_carInfo.staInited = 1;
                    }
                    flag = flag_0;
                }
            } else {  // 已连接STA，重新配网
                if (flag == flag_3) {
                    if (WIFI_SUCCESS == StopStation()) {
                        g_carInfo.staInited = 0;
                    }
                    if (WIFI_SUCCESS == StartStation()) {
                        g_carInfo.staInited = 1;
                    }
                    flag = flag_0;
                }
            }
        }
        usleep(1000*1000);
    }

    retCode = UnRegisterWifiEventListener();
    if (g_carInfo.apInited == 1) {
        if (WIFI_SUCCESS == StopHotspot()) {
            g_carInfo.apInited = 0;
        }
    }
    if (g_carInfo.staInited == 1) {  // 关闭STA模式
        if (WIFI_SUCCESS == StopStation()) {
            g_carInfo.staInited = 0;
        }
    }
    #if SERVER_UDP
    if (g_carInfo.udpServRecvTaskId != NULL) {
        UdpSocketDeInit();
        osThreadTerminate(g_carInfo.udpServRecvTaskId);
        g_carInfo.udpServRecvTaskId = NULL;
    }
    #endif
    #if SERVER_TCP
    if (g_carInfo.tcpServRecvTaskId != NULL) {
        TcpSocketDeInit();
        osThreadTerminate(g_carInfo.tcpServRecvTaskId);
        g_carInfo.tcpServRecvTaskId = NULL;
    }
    #endif

    g_carInfo.netCtrlTaskId = NULL;
}

osThreadId_t NetCtrlTaskEntry(void)
{
    //osPriorityAboveNormal[32], osPriorityNormal[24]
    //{.name, .attr_bits, .cb_mem, .cb_size, .stack_mem, .stack_size, .priority, .tz_module, .reserved}
    osThreadAttr_t attr = {"NetCtrlTask", 0, NULL, 0, NULL, 1024*4, 24, 0, 0};
    osThreadId_t taskId = osThreadNew(NetCtrlTask, NULL, &attr);
    if (taskId == NULL) {
        printf("%s: Failed to create %s!\n", __func__, attr.name);
        return NULL;
    }
    return taskId;
}
